using Microsoft.Extensions.Configuration;
using Org.BouncyCastle.Crypto.Prng;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;

namespace CR.API.Services
{
    /// <summary>
    /// 云存储验证码服务实现
    /// </summary>
    public class CloudCaptchaService : ICaptchaService
    {
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly IConfiguration _configuration;
        private readonly IMemoryCache _memoryCache;
        private readonly Random _random;
        private const string CaptchaCacheKeyPrefix = "CAPTCHA_";
        private const int CaptchaExpirationMinutes = 5;

        // 验证码配置
        private const int CaptchaWidth = 120;
        private const int CaptchaHeight = 40;
        private const int CaptchaLength = 4;
        
        // 假设这是云存储API的URL
        private readonly string _cloudStorageUrl;
        
        public CloudCaptchaService(
            IHttpClientFactory httpClientFactory, 
            IConfiguration configuration, 
            IMemoryCache memoryCache)
        {
            _httpClientFactory = httpClientFactory;
            _configuration = configuration;
            _memoryCache = memoryCache;
            _random = new Random();
            
            // 从配置中获取云存储URL
            _cloudStorageUrl = _configuration["CloudStorage:ApiUrl"] ?? "https://api.yourcloudprovider.com/upload";
        }

        /// <summary>
        /// 生成验证码
        /// </summary>
        /// <returns>验证码ID和图片URL</returns>
        public async Task<(string captchaId, string imageUrl)> GenerateCaptchaAsync()
        {
            // 生成随机验证码
            string captchaText = GenerateRandomCode(CaptchaLength);
            
            // 生成验证码图片
            byte[] imageBytes = GenerateCaptchaImage(captchaText);
            
            // 上传到云存储
            string imageUrl = await UploadToCloudStorageAsync(imageBytes);
            
            // 生成唯一ID
            string captchaId = Guid.NewGuid().ToString("N");
            
            // 缓存验证码文本，用于后续验证
            _memoryCache.Set(
                $"{CaptchaCacheKeyPrefix}{captchaId}", 
                captchaText, 
                TimeSpan.FromMinutes(CaptchaExpirationMinutes));
            
            return (captchaId, imageUrl);
        }

        /// <summary>
        /// 验证验证码
        /// </summary>
        /// <param name="captchaId">验证码ID</param>
        /// <param name="userInput">用户输入的验证码</param>
        /// <returns>是否验证通过</returns>
        public Task<bool> ValidateCaptchaAsync(string captchaId, string userInput)
        {
            if (string.IsNullOrWhiteSpace(captchaId) || string.IsNullOrWhiteSpace(userInput))
            {
                return Task.FromResult(false);
            }
            
            // 从缓存中获取验证码文本
            string cacheKey = $"{CaptchaCacheKeyPrefix}{captchaId}";
            
            if (_memoryCache.TryGetValue(cacheKey, out string captchaText))
            {
                // 验证后移除缓存，防止重复使用
                _memoryCache.Remove(cacheKey);
                
                // 不区分大小写比较
                return Task.FromResult(string.Equals(
                    captchaText, 
                    userInput, 
                    StringComparison.OrdinalIgnoreCase));
            }
            
            return Task.FromResult(false);
        }

        /// <summary>
        /// 生成随机验证码
        /// </summary>
        private string GenerateRandomCode(int length)
        {
            // 避免使用容易混淆的字符，如0和O，1和l
            const string chars = "2346789ABCDEFGHJKLMNPQRTUVWXYabcdefghijkmnpqrtuvwxy";
            
            var stringBuilder = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                stringBuilder.Append(chars[_random.Next(chars.Length)]);
            }
            
            return stringBuilder.ToString();
        }

        /// <summary>
        /// 生成验证码图片
        /// </summary>
        private byte[] GenerateCaptchaImage(string captchaText)
        {
            using (var bitmap = new Bitmap(CaptchaWidth, CaptchaHeight))
            using (var graphics = Graphics.FromImage(bitmap))
            using (var memoryStream = new MemoryStream())
            {
                // 填充背景
                graphics.Clear(Color.White);
                
                // 添加噪点
                AddNoise(graphics, bitmap.Width, bitmap.Height);
                
                // 绘制干扰线
                AddInterferenceLines(graphics, bitmap.Width, bitmap.Height);
                
                // 绘制文字
                DrawCaptchaText(graphics, captchaText);
                
                // 保存为JPEG
                bitmap.Save(memoryStream, ImageFormat.Jpeg);
                
                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// 添加噪点
        /// </summary>
        private void AddNoise(Graphics graphics, int width, int height)
        {
            using (var brush = new SolidBrush(Color.Gray))
            {
                for (int i = 0; i < 100; i++)
                {
                    int x = _random.Next(width);
                    int y = _random.Next(height);
                    graphics.FillRectangle(brush, x, y, 1, 1);
                }
            }
        }

        /// <summary>
        /// 添加干扰线
        /// </summary>
        private void AddInterferenceLines(Graphics graphics, int width, int height)
        {
            using (var pen = new Pen(Color.LightGray))
            {
                for (int i = 0; i < 5; i++)
                {
                    int x1 = _random.Next(width);
                    int y1 = _random.Next(height);
                    int x2 = _random.Next(width);
                    int y2 = _random.Next(height);
                    
                    graphics.DrawLine(pen, x1, y1, x2, y2);
                }
            }
        }

        /// <summary>
        /// 绘制验证码文本
        /// </summary>
        private void DrawCaptchaText(Graphics graphics, string captchaText)
        {
            // 字体集合
            var fontNames = new[] { "Arial", "Verdana", "Times New Roman", "Georgia", "Courier New" };
            
            for (int i = 0; i < captchaText.Length; i++)
            {
                // 随机字体、大小、样式、颜色
                int fontSize = _random.Next(14, 20);
                string fontName = fontNames[_random.Next(fontNames.Length)];
                FontStyle fontStyle = (FontStyle)_random.Next(0, 3); // 0=Regular, 1=Bold, 2=Italic
                
                using (var font = new Font(fontName, fontSize, fontStyle))
                using (var brush = new SolidBrush(GetRandomColor()))
                {
                    // 随机偏移
                    float x = i * CaptchaWidth / captchaText.Length + _random.Next(-3, 3);
                    float y = _random.Next(2, 10);
                    
                    // 随机旋转
                    float angle = _random.Next(-10, 10);
                    graphics.TranslateTransform(x + fontSize / 2, y + fontSize / 2);
                    graphics.RotateTransform(angle);
                    graphics.DrawString(captchaText[i].ToString(), font, brush, 0, 0);
                    graphics.ResetTransform();
                }
            }
        }

        /// <summary>
        /// 获取随机颜色
        /// </summary>
        private Color GetRandomColor()
        {
            // 使用较深的颜色以增加可读性
            int r = _random.Next(0, 150);
            int g = _random.Next(0, 150);
            int b = _random.Next(0, 150);
            
            return Color.FromArgb(r, g, b);
        }

        /// <summary>
        /// 上传到云存储服务
        /// </summary>
        private async Task<string> UploadToCloudStorageAsync(byte[] imageBytes)
        {
            try
            {
                // 创建HttpClient
                var httpClient = _httpClientFactory.CreateClient();
                
                // 准备multipart表单数据
                using var formData = new MultipartFormDataContent();
                var imageContent = new ByteArrayContent(imageBytes);
                imageContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");
                formData.Add(imageContent, "file", $"captcha_{Guid.NewGuid():N}.jpg");
                
                // 添加任何必要的认证信息
                string apiKey = _configuration["CloudStorage:ApiKey"];
                if (!string.IsNullOrEmpty(apiKey))
                {
                    httpClient.DefaultRequestHeaders.Add("X-API-Key", apiKey);
                }
                
                // 发送请求
                var response = await httpClient.PostAsync(_cloudStorageUrl, formData);
                response.EnsureSuccessStatusCode();
                
                // 解析响应获取URL
                var responseContent = await response.Content.ReadAsStringAsync();
                
                // 实际实现中，需要根据云服务API的响应格式解析出URL
                // 这里为了演示，直接返回一个模拟的URL
                // 在实际项目中，需要替换为真实的云存储服务
                return $"https://storage.yourcloudprovider.com/captcha/captcha_{Guid.NewGuid():N}.jpg";
            }
            catch (Exception ex)
            {
                // 异常处理
                // 在生产环境中应该记录日志
                Console.WriteLine($"云存储上传失败: {ex.Message}");
                
                // 如果云存储上传失败，使用本地存储的临时方案
                return await SaveToLocalStorageAsync(imageBytes);
            }
        }

        /// <summary>
        /// 保存到本地存储（临时备选方案）
        /// </summary>
        private Task<string> SaveToLocalStorageAsync(byte[] imageBytes)
        {
            try
            {
                // 创建本地目录
                var uploadDir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "captcha");
                if (!Directory.Exists(uploadDir))
                {
                    Directory.CreateDirectory(uploadDir);
                }
                
                // 生成文件名
                string fileName = $"captcha_{Guid.NewGuid():N}.jpg";
                string filePath = Path.Combine(uploadDir, fileName);
                
                // 保存文件
                File.WriteAllBytes(filePath, imageBytes);
                
                // 返回访问URL
                string baseUrl = _configuration["BaseUrl"] ?? "http://localhost:5203";
                return Task.FromResult($"{baseUrl}/captcha/{fileName}");
            }
            catch (Exception ex)
            {
                // 异常处理
                Console.WriteLine($"本地存储失败: {ex.Message}");
                
                // 如果所有方法都失败，返回一个静态URL
                return Task.FromResult("/static/default-captcha.jpg");
            }
        }
    }
} 